package com.party.api.service.wechat.impl;

import com.alibaba.fastjson.JSONObject;
import com.party.api.dto.wechat.requst.CustomRequest;
import com.party.api.dto.wechat.requst.MaterialListRequest;
import com.party.api.dto.wechat.requst.MenuRequest;
import com.party.api.dto.wechat.requst.XcxQrCodeRequest;
import com.party.api.dto.wechat.response.*;
import com.party.api.service.wechat.IWechatService;
import com.party.common.constant.WechatConstant;
import com.party.common.utils.StringUtils;
import com.party.common.utils.wechat.WechatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 微信服务接口
 * Created by wei.li
 *
 * @date 2017/8/28 0028
 * @time 11:35
 */

@Service
public class WechatService implements IWechatService {

    public static String ACCESS_TOKEN = "ACCESS_TOKEN";

    protected static Logger logger = LoggerFactory.getLogger(WechatService.class);


    /**
     * 创建微信菜单
     * @param menuRequest 请求参数
     * @param accessToken 公众号令牌
     * @return 响应参数
     */
    @Override
    public Response createMenu(MenuRequest menuRequest, String accessToken) {
        String url = WechatConstant.CREATE_MENU_URL.replace(ACCESS_TOKEN, accessToken);

        logger.info("微信菜单请求参数{}", JSONObject.toJSONString(menuRequest));
        JSONObject response = WechatUtils.httpRequest(url, WechatConstant.POST, JSONObject.toJSONString(menuRequest));
        logger.info("微信菜单响应参数{}", response.toJSONString());

        Response menuResponse = JSONObject.toJavaObject(response, Response.class);
        return menuResponse;
    }


    /**
     * 获取菜单
     * @param accessToken 公众号令牌
     * @return 响应参数
     */
    @Override
    public GetMenuResponse getMenu(String accessToken) {
        String url = WechatConstant.GET_MENU_URL.replace(ACCESS_TOKEN, accessToken);

        logger.info("获取微信菜单请求报文{}", url);
        JSONObject response = WechatUtils.httpRequest(url, WechatUtils.GET, null);
        logger.info("获取微信菜单响应报文{}", response.toJSONString());

        GetMenuResponse getMenuResponse = JSONObject.toJavaObject(response, GetMenuResponse.class);
        return getMenuResponse;
    }

    /**
     * 发送客服消息
     * @param customRequest 请求参数
     * @param accessToken 公众号令牌
     * @return 响应参数
     */
    @Override
    public Response customSend(CustomRequest customRequest, String accessToken) {

        String url = WechatConstant.CUSTOM_SEND_URL.replace(ACCESS_TOKEN, accessToken);

        logger.info("发送客服消息请求报文{}", JSONObject.toJSON(customRequest));
        JSONObject jsonObject = WechatUtils.httpRequest(url, WechatUtils.POST, JSONObject.toJSONString(customRequest));

        logger.info("发送客服消息响应报文{}", jsonObject.toJSONString());
        return JSONObject.toJavaObject(jsonObject, Response.class);
    }

    /**
     * 删除微信菜单
     * @param accessToken 公众号令牌
     * @return 操作结果
     */
    public boolean deleteMenu(String accessToken){
        String url = WechatConstant.DELETE_MENU_URL.replace(ACCESS_TOKEN,accessToken);
        JSONObject jsonObj = WechatUtils.httpRequest(url,"GET",null);
        WechatErrResponse resp = JSONObject.toJavaObject(jsonObj,WechatErrResponse.class);
        if("0".equals(resp.getErrcode())){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 获取永久素材列表
     * @param req 请求的素材列表
     * @param accessToken
     * @return 素材列表的具体内容
     */
    public MaterialListResponse getMaterialList(MaterialListRequest req, String accessToken){
        String url = WechatConstant.BATCHGET_MATERIAL_URL.replace(ACCESS_TOKEN,accessToken);
        logger.info("获取永久素材URL：{}",url);
        logger.info("获取永久素材列表报文：{}",JSONObject.toJSONString(req));
        JSONObject jsonObj = WechatUtils.httpRequest(url,"POST", JSONObject.toJSONString(req));
        logger.info("微信响应报文：{}",jsonObj.toString());
        if(jsonObj.containsKey("errcode")){
            return null;
        }else{
            return JSONObject.toJavaObject(jsonObj,MaterialListResponse.class);
        }
    }

    @Override
    public InputStream createMiniProgramQrCode(XcxQrCodeRequest qrCodeRequest, String accessToken) {
        String url = WechatConstant.MINI_PROGRAM_QR_CODE_URL.replace(ACCESS_TOKEN, accessToken);
        logger.info("生成二维码请求参数：{}", JSONObject.toJSONString(qrCodeRequest));
        InputStream inputStream = WechatUtils.httpRequestInputStream(url, "POST", JSONObject.toJSONString(qrCodeRequest));
        return inputStream;
    }

    /**
     * 上传临时素材
     * @param file: 文件
     * @param accessToken
     * @param type: 素材类型
     * @return
     * @throws IOException
     */
    @Override
    public UploadTempMediaResponse uploadTempMedia(File file, String accessToken, String type) throws IOException {
        logger.info("上传临时素材请求报文: file = {}, accessToken = {}, type = {}", file, accessToken, type);
        String urlString = WechatConstant.UPLOAD_TEMP_MEDIA_URL.replace(ACCESS_TOKEN, accessToken)
                .replace("TYPE", type);

        StringBuffer buffer = new StringBuffer();

        //1.建立连接
        URL url = new URL(urlString);
        HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  //打开链接

        //1.1输入输出设置
        httpUrlConn.setDoInput(true);
        httpUrlConn.setDoOutput(true);
        httpUrlConn.setUseCaches(false); // post方式不能使用缓存
        //1.2设置请求头信息
        httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
        httpUrlConn.setRequestProperty("Charset", "UTF-8");
        //1.3设置边界
        String BOUNDARY = "----------" + System.currentTimeMillis();
        httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY);

        // 请求正文信息
        // 第一部分：
        //2.将文件头输出到微信服务器
        StringBuilder sb = new StringBuilder();
        sb.append("--"); // 必须多两道线
        sb.append(BOUNDARY);
        sb.append("\r\n");
        sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length()
                + "\";filename=\""+ file.getName() + "\"\r\n");
        sb.append("Content-Type:application/octet-stream\r\n\r\n");
        byte[] head = sb.toString().getBytes("utf-8");
        // 获得输出流
        OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream());
        // 将表头写入输出流中：输出表头
        outputStream.write(head);

        //3.将文件正文部分输出到微信服务器
        // 把文件以流文件的方式 写入到微信服务器中
        DataInputStream in = new DataInputStream(new FileInputStream(file));
        int bytes = 0;
        byte[] bufferOut = new byte[1024];
        while ((bytes = in.read(bufferOut)) != -1) {
            outputStream.write(bufferOut, 0, bytes);
        }
        in.close();
        //4.将结尾部分输出到微信服务器
        byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
        outputStream.write(foot);
        outputStream.flush();
        outputStream.close();

        //5.将微信服务器返回的输入流转换成字符串
        InputStream inputStream = httpUrlConn.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

        String str = null;
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }

        bufferedReader.close();
        inputStreamReader.close();
        // 释放资源
        inputStream.close();
        httpUrlConn.disconnect();

        logger.info("上传临时素材响应参数报文 uploadTempMediaResponse = {}", buffer.toString());
        UploadTempMediaResponse uploadTempMediaResponse = JSONObject.parseObject(buffer.toString(), UploadTempMediaResponse.class);

        if (null == uploadTempMediaResponse || StringUtils.isEmpty(uploadTempMediaResponse.getMediaId())) {
            logger.error("上传临时素材异常：{}", buffer.toString());
        }
        return uploadTempMediaResponse;
    }
}
